package com.storlead.sjwt.security;

import com.alibaba.fastjson.JSONObject;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.util.JSONPObject;
import com.storlead.sjwt.model.JwtUser;
import com.storlead.sjwt.model.LoginUser;
import com.storlead.sjwt.model.Result;
import com.storlead.sjwt.util.JwtTokenUtils;
import lombok.extern.slf4j.Slf4j;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
import org.springframework.stereotype.Component;

import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.*;

/**
 * @Author: Timo
 * @Date: 2019/3/21 11:56
 * @Description: 拦截器
 * 这里时进行用户账户的验证
 */
//@Slf4j
//@Component
public class JWTAuthenticationFilter extends UsernamePasswordAuthenticationFilter {
    private static Logger log = LoggerFactory.getLogger(JWTAuthenticationFilter.class);
    //认证器
    private AuthenticationManager authenticationManager;

    /**
     * 设置认证器
     *
     * @param authenticationManager
     */
    public JWTAuthenticationFilter(AuthenticationManager authenticationManager) {
        this.authenticationManager = authenticationManager;
//        super.setFilterProcessesUrl("/sys/login");
    }

    @Override
    public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response) throws AuthenticationException {

        try {
            // 获取用户登陆填写的表单信息
            LoginUser loginUser = new ObjectMapper().readValue(request.getInputStream(), LoginUser.class);
            UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken(loginUser.getUsername(), loginUser.getPassword(), new ArrayList<>());
            return authenticationManager.authenticate(token);
        } catch (IOException e) {
            e.printStackTrace();
        }
        return null;
    }

    /**
     * 认证成功之后返回token
     *
     * @param request
     * @param response
     * @param chain
     * @param authResult
     * @throws IOException
     * @throws ServletException
     */
    @Override
    protected void successfulAuthentication(HttpServletRequest request, HttpServletResponse response, FilterChain chain, Authentication authResult) throws IOException, ServletException {
        JwtUser jwtUser = (JwtUser) authResult.getPrincipal();
        String roleCode = null;


        Collection<? extends GrantedAuthority> authorities = jwtUser.getAuthorities();
        for (GrantedAuthority authority : authorities) {
            roleCode = authority.getAuthority();
            break;
        }
        log.info("jwtUser:{}", jwtUser.toString());
        Map<String, Object> resultMap = new HashMap<>();
        String token = JwtTokenUtils.createToken(jwtUser.getUsername(), roleCode, false);
        resultMap.put("token", token);
        Result result = Result.success(resultMap);
        response.setHeader("token", JwtTokenUtils.TOKEN_PREFIX + token);
        response.getWriter().write(JSONObject.toJSONString(result));
    }

    /**
     * 登陆失败处理
     *
     * @param request
     * @param response
     * @param failed
     * @throws IOException
     * @throws ServletException
     */
    @Override
    protected void unsuccessfulAuthentication(HttpServletRequest request, HttpServletResponse response, AuthenticationException failed) throws IOException, ServletException {
        Result result = Result.failure("authentication failed, reason: " + failed.getMessage());
        response.getWriter().write(JSONObject.toJSONString(result));
    }
}
